package lv.odo.openbravo.localization;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class OdoStringUtilities {

	public static String[] monthsLocative = new String[] { "janv\u0101r\u012B",
			"febru\u0101r\u012B", "mart\u0101", "apr\u012Bl\u012B",
			"maij\u0101", "j\u016Bnij\u0101", "j\u016Blij\u0101",
			"august\u0101", "septembr\u012B", "oktobr\u012B", "decembr\u012B" };

	public static String[] lati = new String[] { "latu", "lats", "lati" };
	public static String[] santimi = new String[] { "sant\u012Bmu",
			"sant\u012Bms", "sant\u012Bmi" };
	public static String[] ones = new String[] { null, "viens", "divi",
			"tr\u012Bs", "\u010Detri", "pieci", "se\u0161i", "septi\u0146i",
			"asto\u0146i", "devi\u0146i", "desmit", "vienpadsmit",
			"divpadsmit", "tr\u012Bspadsmit", "\u010Detrpadsmit",
			"piecpadsmit", "se\u0161padsmit", "septi\u0146padsmit",
			"asto\u0146padsmit", "devi\u0146padsmit" };
	public static String[] tens = new String[] { null, null, "divdesmit",
			"tr\u012Bsdesmit", "\u010Detrdesmit", "piecdesmit",
			"se\u0161desmit", "septi\u0146desmit", "asto\u0146desmit",
			"devi\u0146desmit" };
	/*
	 * public static String[] hundreds = new String[] { null, "simts",
	 * "divi simti", "tr\u012Bs simti", "\u010Detri simti", "pieci simti",
	 * "se\u0161i simti", "septi\u0146i simti", "asto\u0146i simti",
	 * "devi\u0146i simti" };
	 */
	public static String[] hundreds = new String[] { null, "simts", "divsimt",
			"tr\u012Bssimt", "\u010Detrsimt", "piecsimt", "se\u0161simt",
			"septi\u0146simt", "asto\u0146simt", "devi\u0146simt" };
	public static String[] singularPowers = new String[] { null,
			"t\u016Bkstotis", "miljons", "miljards", "triljons" };
	public static String[] pluralPowers = new String[] { null,
			"t\u016Bksto\u0161i", "miljoni", "miljardi", "triljoni" };

	public static String getDateLocative(java.util.Date d) {
		GregorianCalendar c = new GregorianCalendar();
		c.setTime(d);
		return "" + c.get(Calendar.YEAR) + ". gada " + c.get(Calendar.DATE)
				+ ". " + monthsLocative[c.get(Calendar.MONTH)];
	}

	public static String getAddressString(String address1, String address2,
			String city, String region, String country, String postal) {
		StringBuffer result = new StringBuffer();
		String[] args = new String[] { address1, address2, city, region,
				country, postal };
		for (int i = 0; i < args.length; i++) {
			if (args[i] != null && !args[i].trim().equals("")) {
				if (result.length() > 0) {
					result.append(", ");
				}
				result.append(args[i].trim());
			}
		}
		return result.toString();
	}
	
	public static String moneyInWords(String amount) {
		return moneyInWords(new BigDecimal(amount), BigDecimal.ZERO);
	}

	/**
	 * Prints the sum in Latvian (lats and santimes).
	 */
	public static String moneyInWords(BigDecimal totalLineNetAmt,
			BigDecimal totalTaxAmt) {
		if (totalLineNetAmt == null || totalTaxAmt == null) {
			return "Nulle latu, nulle sant\u012Bmu";
		}
		try {
			BigDecimal total = totalLineNetAmt.add(totalTaxAmt);
			if (total.compareTo(BigDecimal.ZERO) == 0) {
				return "Nulle latu, nulle sant\u012Bmu";
			} else if (total.compareTo(BigDecimal.ZERO) == -1) {
				return "M\u012Bnus " + positiveMoneyInWords(total.negate());
			} else {
				String s = positiveMoneyInWords(total);
				return s.substring(0, 1).toUpperCase() + s.substring(1);
			}
		} catch (RuntimeException e) { // overflow - amount larger than 10^15 or
			// more
			return "Nulle latu, nulle sant\u012Bmu";
		}
	}

	public static String inflectUom(String stem, int r) {
		if (r % 10 == 0) {
			return stem + "u";
		} else if (r % 10 == 1 && r != 11) {
			return stem + "s";
		} else {
			return stem + "i";
		}
	}

	public static String positiveMoneyInWords(BigDecimal arg) {
		// arg = arg.round(new MathContext(2));
		long integerPart = arg.longValue();
		BigDecimal fractionPart = arg.subtract(new BigDecimal(integerPart));
		long hundredths = fractionPart.multiply(new BigDecimal("100"))
				.longValue();
		if (fractionPart.multiply(new BigDecimal("100")).subtract(
				new BigDecimal(hundredths)).doubleValue() >= 0.5) {
			hundredths += 1;
		}

		String stem1 = "lat";
		String stem2 = "sant\u012Bm";
		int r1 = (int) integerPart % 100;
		int r2 = (int) hundredths % 100;
		return spellLong(integerPart).trim() + " " + inflectUom(stem1, r1)
				+ ", " + spellLong(hundredths).trim() + " "
				+ inflectUom(stem2, r2);
	}

	public static String spellLong(long arg) {
		if (arg == 0L) {
			return "nulle";
		} else {
			return spellPositiveLong(arg);
		}
	}

	public static String spellPositiveLong(long arg) {
		if (arg == 0L) {
			return "";
		} else if (arg < 20L) {
			return ones[(int) arg];
		} else if (arg < 100L) {
			long a = arg / 10L;
			long b = arg - 10L * a;
			return tens[(int) a] + " " + spellPositiveLong(b);
		} else if (arg < 1000L) {
			long a = arg / 100L;
			long b = arg - 100L * a;
			return hundreds[(int) a] + " " + spellPositiveLong(b);
		} else if (arg < 1000L * 1000L) {
			long a = arg / 1000L;
			long b = arg - 1000 * a;
			return spellPositiveLong(a) + " "
					+ ((a % 10L == 1L) ? singularPowers[1] : pluralPowers[1])
					+ " " + spellPositiveLong(b);
		} else if (arg < 1000L * 1000L * 1000L) {
			long a = arg / (1000L * 1000L);
			long b = arg - (1000L * 1000L) * a;
			return spellPositiveLong(a) + " "
					+ ((a % 10L == 1L) ? singularPowers[2] : pluralPowers[2])
					+ " " + spellPositiveLong(b);
		} else if (arg < 1000L * 1000L * 1000L * 1000L) {
			long a = arg / (1000L * 1000L * 1000L);
			long b = arg - (1000L * 1000L * 1000L) * a;
			return spellPositiveLong(a) + " "
					+ ((a % 10L == 1L) ? singularPowers[3] : pluralPowers[3])
					+ " " + spellPositiveLong(b);

		} else if (arg < 1000L * 1000L * 1000L * 1000L * 1000L) {
			long a = arg / (1000L * 1000L * 1000L * 1000L);
			long b = arg - (1000L * 1000L * 1000L * 1000L) * a;
			return spellPositiveLong(a) + " "
					+ ((a % 10L == 1L) ? singularPowers[4] : pluralPowers[4])
					+ " " + spellPositiveLong(b);

		} else {
			throw new RuntimeException("overflow");
		}
	}

	// public static String

	@SuppressWarnings("unused")
	private static List<Long> parseMoney(String money) {
		Pattern p1 = Pattern.compile("(-)?([0-9]*)((\\.|,)([0-9]{0,2}))?");
		Matcher m = p1.matcher(money);
		if (m.matches()) {
			long lats = Long.parseLong(m.group(2));
			long santimes = Long.parseLong(m.group(5));
			return Arrays.asList(new Long[] { lats, santimes });
		} else {
			return Arrays.asList(new Long[] { 0L, 0L });
		}
	}
}
